﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using UnityEngine;

/// <summary>
/// 采用littleEndian小头模式的MemoryStream
/// 备注：这个类生成的数据流，与服务端java生成的数据流是兼容的！因为服务端我们的java读写数据流相关代码是按小头模式自己开发的。
/// 
/// 
/// 单元检查人签名：cxs
/// 单元检查日期：2014_7_25
/// 
/// </summary>
public class MemoryStream_LittleEndian : MemoryStream
{

#region 构造函数
    // 摘要:
        //     使用初始化为零的可扩展容量初始化 System.IO.MemoryStream 类的新实例。
        public MemoryStream_LittleEndian():base(){}
        //
        // 摘要:
        //     基于指定的字节数组初始化 System.IO.MemoryStream 类的无法调整大小的新实例。
        //
        // 参数:
        //   buffer:
        //     从中创建当前流的无符号字节数组。
        //
        // 异常:
        //   System.ArgumentNullException:
        //     buffer 为 null。
        public MemoryStream_LittleEndian(byte[] buffer):base(buffer){}
        //
        // 摘要:
        //     使用按指定要求初始化的可扩展容量初始化 System.IO.MemoryStream 类的新实例。
        //
        // 参数:
        //   capacity:
        //     内部数组的初始大小（以字节为单位）。
        //
        // 异常:
        //   System.ArgumentOutOfRangeException:
        //     capacity 为负。
        public MemoryStream_LittleEndian(int capacity):base(capacity){}
        //
        // 摘要:
        //     使用按指定要求设置的 System.IO.MemoryStream.CanWrite 属性基于指定的字节数组初始化 System.IO.MemoryStream
        //     类的无法调整大小的新实例。
        //
        // 参数:
        //   buffer:
        //     从中创建该流的无符号字节数组。
        //
        //   writable:
        //     System.IO.MemoryStream.CanWrite 属性的设置，确定流是否支持写入。
        //
        // 异常:
        //   System.ArgumentNullException:
        //     buffer 为 null。
        public MemoryStream_LittleEndian(byte[] buffer, bool writable):base(buffer, writable){}
        //
        // 摘要:
        //     基于字节数组的指定区域（索引）初始化 System.IO.MemoryStream 类的无法调整大小的新实例。
        //
        // 参数:
        //   buffer:
        //     从中创建该流的无符号字节数组。
        //
        //   index:
        //     buffer 内的索引，流从此处开始。
        //
        //   count:
        //     流的长度（以字节为单位）。
        //
        // 异常:
        //   System.ArgumentNullException:
        //     buffer 为 null。
        //
        //   System.ArgumentOutOfRangeException:
        //     index 或 count 小于零。
        //
        //   System.ArgumentException:
        //     index 与 count 的和大于 buffer 的长度。
        public MemoryStream_LittleEndian(byte[] buffer, int index, int count):base(buffer,index, count){}
        //
        // 摘要:
        //     使用按指定要求设置的 System.IO.MemoryStream.CanWrite 属性基于字节数组的指定区域初始化 System.IO.MemoryStream
        //     类的无法调整大小的新实例。
        //
        // 参数:
        //   buffer:
        //     从中创建该流的无符号字节数组。
        //
        //   index:
        //     buffer 内的索引，流从此处开始。
        //
        //   count:
        //     流的长度（以字节为单位）。
        //
        //   writable:
        //     System.IO.MemoryStream.CanWrite 属性的设置，确定流是否支持写入。
        //
        // 异常:
        //   System.ArgumentNullException:
        //     buffer 为 null。
        //
        //   System.ArgumentOutOfRangeException:
        //     index 或 count 为负。
        //
        //   System.ArgumentException:
        //     index 与 count 的和大于 buffer 的长度。
        public MemoryStream_LittleEndian(byte[] buffer, int index, int count, bool writable):base(buffer, index, count, writable){}
        //
        // 摘要:
        //     在按指定要求设置 System.IO.MemoryStream.CanWrite 属性而且能够调用按指定要求设置的 System.IO.MemoryStream.GetBuffer()
        //     的情况下，基于字节数组的指定区域初始化 System.IO.MemoryStream 类的新实例。
        //
        // 参数:
        //   buffer:
        //     从中创建该流的无符号字节数组。
        //
        //   index:
        //     buffer 内的索引，流从此处开始。
        //
        //   count:
        //     流的长度（以字节为单位）。
        //
        //   writable:
        //     System.IO.MemoryStream.CanWrite 属性的设置，确定流是否支持写入。
        //
        //   publiclyVisible:
        //     设置为 true 可以启用 System.IO.MemoryStream.GetBuffer()，它返回无符号字节数组，流从该数组创建；否则为 false。
        //
        // 异常:
        //   System.ArgumentNullException:
        //     buffer 为 null。
        //
        //   System.ArgumentOutOfRangeException:
        //     index 或 count 为负。
        //
        //   System.ArgumentException:
        //     缓冲区长度减去 index 小于 count。
        public MemoryStream_LittleEndian(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) : base(buffer, index, count, writable, publiclyVisible) { }
#endregion
        







#region 整数
    /// <summary>
    /// 把一个byte数据，以LittleEndian小头模式，写到流中
    /// 备注：byte是一个无符号的整数，取值范围是0 到 255，占用1个字节
    /// </summary>
    /// <param name="value"></param>
    public override void WriteByte(byte value)
    {        
        base.WriteByte(value);
    }

    /// <summary>
    /// 从流中读取一个byte，以LittleEndian小头模式
    /// 备注：byte是一个无符号的整数，取值范围是0 到 255，占用1个字节
    /// </summary>
    /// <param name="value"></param>
    public byte ReadOneByte()
    {
        return (byte)base.ReadByte();
    }   

    /// <summary>
    /// 把一个sbyte数据，以LittleEndian小头模式，写到流中
    /// 备注：sbyte是一个有符号的整数，取值范围是-128 到 127，占用1个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteOneSbyte(sbyte value)
    {
        base.WriteByte((byte)value);
    }

    /// <summary>
    /// 从流中读取一个sbyte，以LittleEndian小头模式
    /// 备注：sbyte是一个有符号的整数，取值范围是-128 到 127，占用1个字节
    /// </summary>
    /// <param name="value"></param>
    public sbyte ReadSbyte()
    {
        return (sbyte)base.ReadByte();
    }

    /// <summary>
    /// 把一个short数据，以LittleEndian小头模式，写到流中
    /// 备注：short是有符号整数，占用2个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteShort(short value)
    {
        byte[] arr = BitConverter.GetBytes(value);

        base.Write(arr,0,arr.Length);
    }

    /// <summary>
    /// 从流中读取一个short数据，以LittleEndian小头模式
    /// 备注：short是有符号整数，占用2个字节
    /// </summary>
    /// <param name="value"></param>
    public short ReadShort()
    {
        byte[] arr=new byte[2];
        base.Read(arr, 0, 2);
        
        return BitConverter.ToInt16(arr, 0);
    }

    /// <summary>
    /// 把一个ushort数据，以LittleEndian小头模式，写到流中
    /// 备注：ushort是无符号整数，占用2个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteUshort(ushort value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个ushort数据，以LittleEndian小头模式
    /// 备注：ushort是无符号整数，占用2个字节
    /// </summary>
    /// <param name="value"></param>
    public ushort ReadUshort()
    {
        byte[] arr = new byte[2];
        base.Read(arr, 0, 2);

        return BitConverter.ToUInt16(arr, 0);
    }


    /// <summary>
    /// 把一个int数据，以LittleEndian小头模式，写到流中
    /// 备注：int是有32符号整数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteInt(int value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个int数据，以LittleEndian小头模式
    /// 备注：int是有符号整数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public int ReadInt()
    {
        byte[] arr = new byte[4];
        base.Read(arr, 0, 4);

        return BitConverter.ToInt32(arr, 0);
    }


    /// <summary>
    /// 把一个uint数据，以LittleEndian小头模式，写到流中
    /// 备注：uint是无32符号整数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteUint(uint value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个uint数据，以LittleEndian小头模式
    /// 备注：uint是无符号整数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public uint ReadUint()
    {
        byte[] arr = new byte[4];
        base.Read(arr, 0, 4);

        return BitConverter.ToUInt32(arr, 0);
    }

    /// <summary>
    /// 把一个long数据，以LittleEndian小头模式，写到流中
    /// 备注：long是有符号64位整数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteLong(long value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个long数据，以LittleEndian小头模式
    /// 备注：long是有符号整数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public long ReadLong()
    {
        byte[] arr = new byte[8];
        base.Read(arr, 0, 8);

        return BitConverter.ToInt64(arr, 0);
    }

    /// <summary>
    /// 把一个ulong数据，以LittleEndian小头模式，写到流中
    /// 备注：ulong是无符号64位整数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteUlong(ulong value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个ulong数据，以LittleEndian小头模式
    /// 备注：ulong是无符号整数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public ulong ReadUlong()
    {
        byte[] arr = new byte[8];
        base.Read(arr, 0, 8);

        return BitConverter.ToUInt64(arr, 0);
    }

    /// <summary>
    /// 从流中读取一个Vecotr3数据，以LittleEndian小头模式
    /// 备注：ulong是无符号整数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public Vector3 ReadVector()
    {
        Vector3 value = new Vector3(Readfloat(), Readfloat(), Readfloat());
        return value;
    }
    /// <summary>
    /// 把一个Vecotr3数据，以LittleEndian小头模式，写到流中
    /// 备注：ulong是无符号64位整数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteVector(Vector3 value)
    {
        WriteFloat(value.x);
        WriteFloat(value.y);
        WriteFloat(value.z);
    }
#endregion

#region 浮点数
    /// <summary>
    /// 把一个float数据，以LittleEndian小头模式，写到流中
    /// 备注：float是单精度浮点数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteFloat(float value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个float数据，以LittleEndian小头模式
    /// 备注：float是单精度浮点数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public float Readfloat()
    {
        byte[] arr = new byte[4];
        base.Read(arr, 0, 4);

        return BitConverter.ToSingle(arr, 0);
    }


    /// <summary>
    /// 把一个double数据，以LittleEndian小头模式，写到流中
    /// 备注：double是双精度浮点数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public void WriteDouble(double value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个double数据，以LittleEndian小头模式
    /// 备注：double是双精度浮点数，占用8个字节
    /// </summary>
    /// <param name="value"></param>
    public double ReadDouble()
    {
        byte[] arr = new byte[8];
        base.Read(arr, 0, 8);
        return BitConverter.ToDouble(arr, 0);
    }

#endregion

#region 字符串
    /// <summary>
    /// 把一个string数据，以LittleEndian小头模式，写到流中
    /// 备注：开头2个字节是字符串长度，后面是字符串内容（utf8格式）
    /// 注意：整个字符串的长度，不能超过65535个字节！超过则报异常！！！！！！！！！！！！！！！！！！！！！
    /// </summary>
    /// <param name="value"></param>
    public void WriteUTF8String(string str)
    {
        byte[] arr = System.Text.Encoding.UTF8.GetBytes(str);
        if (arr.Length > 65535)
        {
            throw new InvalidCastException("error:string length "+arr.Length+" exceed 65535!");
        }
        this.WriteUshort((ushort)arr.Length);

        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个string数据，以LittleEndian小头模式，写到流中
    /// 备注：开头2个字节是字符串长度，后面是字符串内容（utf8格式）
    /// 注意：整个字符串的长度，不超过65535个字节！！！！！！！！！！！！！！！！！！！！！！！！！！！！！
    /// </summary>
    /// <param name="value"></param>
    public string ReadUTF8String()
    {
        ushort ilen=this.ReadUshort();//字节长度

        byte[] arr = new byte[ilen];
        base.Read(arr, 0, ilen);
        return Encoding.UTF8.GetString(arr);

    }

#endregion

#region 字节数组相关
    /// <summary>
    /// 读指定个数的字节
    /// </summary>
    /// <param name="iLen"></param>
    /// <returns></returns>
    public byte[] ReadBytes()
    {
        int iLen = ReadInt();
        byte[] arr = new byte[iLen];
        base.Read(arr, 0, iLen);
        return arr;
    }

    /// <summary>
    /// 写指定个数的字节
    /// </summary>
    /// <param name="iLen"></param>

    public void WriteBytes(byte[] arr, bool shouldWriteLen =true)
    {
        if (shouldWriteLen)
        {
            WriteInt(arr.Length);
        }
        base.Write(arr, 0, arr.Length);
    }
    #endregion

#region 布尔值
    public void WriteBool(bool value)
    {
        byte[] arr = BitConverter.GetBytes(value);
        base.Write(arr, 0, arr.Length);
    }

    /// <summary>
    /// 从流中读取一个float数据，以LittleEndian小头模式
    /// 备注：float是单精度浮点数，占用4个字节
    /// </summary>
    /// <param name="value"></param>
    public bool ReadBool()
    {
        byte[] arr = new byte[sizeof(bool)];
        base.Read(arr, 0, sizeof(bool));

        return BitConverter.ToBoolean(arr, 0);
    }
#endregion

}
